import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.Timer;
import java.util.TimerTask;

import Interfaces.IManagmentChannel;
import Messages.DiscoveryMessage;
import Messages.OSTypeEnum;


public class ManagmentChannel implements IManagmentChannel 
{
	private MulticastSocket m_socket;
	private String m_ip;
	private int m_port;
	private Timer m_discoveryTimer;
	private DiscoveryMessage m_discoveryMessage;
	private int m_intervalInMilisec;
	
	/*
	 * ip: multicast group ip
	 * port: multicast port
	 * intervalInMilisec: send discovery message timer interval in mili seconds.
	 */
	public ManagmentChannel(String ip, int port, int intervalInMilisec) throws IOException
	{
		m_ip = ip;
		m_port = port;
		m_intervalInMilisec = intervalInMilisec;
		m_discoveryTimer = new Timer();
		m_discoveryMessage = new DiscoveryMessage();
		m_discoveryMessage.AgentIP = InetAddress.getLocalHost().getHostAddress();
		m_discoveryMessage.AgentHost = InetAddress.getLocalHost().getHostName();
		m_discoveryMessage.OSType = OSTypeEnum.Windows;
		m_discoveryMessage.AgentListeningPort = 6000;
	}
	
	@Override
	public void Start() throws IOException 
	{
		// Create the multicast socket
		m_socket = new MulticastSocket();
		
		// Start the timer. timer interval 1000 milisec
		m_discoveryTimer.scheduleAtFixedRate(new TimerTask() {
			  @Override
			  public void run() 
			  {
				  try 
				  {
					  ByteArrayOutputStream byteStream = new ByteArrayOutputStream(5000);
				      ObjectOutputStream os = new ObjectOutputStream(new BufferedOutputStream(byteStream));
				      os.flush();
				      os.writeObject(m_discoveryMessage);
				      os.flush();
				      // Retrieves byte array
				      byte[] sendBuf = byteStream.toByteArray();
				      DatagramPacket packet = new DatagramPacket(sendBuf, sendBuf.length, InetAddress.getByName(m_ip), m_port);
				      m_socket.send(packet);
				      System.out.println("Send discovery message: " + packet.getAddress() + " " + packet.getPort());
				      os.close();
				  } 
				  catch (IOException e) 
				  {
					e.printStackTrace();
				  }
			  }
			}, 0, m_intervalInMilisec);
	}

	@Override
	public void Stop() 
	{
		// Stop the timer
		m_discoveryTimer.cancel();
		
		// Close the multicast socket
		if (m_socket != null)
			m_socket.close();
	}
}
